package viper.receive;

/*****************************************
 * Extractor.java
 * ----------------
 * Revision: v.1.0
 * Author: Ji Kim
 * Date Created: 12/13/2009
 * Description:
 * Last Back-Up:
 * Revision History:
 *****************************************/

import java.awt.*;
import java.io.IOException;
import java.util.Vector;
import java.util.Enumeration;
import javax.media.*;
import javax.media.format.*;
import javax.media.protocol.*;
import javax.media.datasink.*;
import javax.media.control.MonitorControl;
import java.io.*;
import java.net.*;

public class Extractor implements BufferTransferHandler {

	DataSource ds;
	PushBufferStream streams[];
	Buffer buff;
	LiveStream ls;
	Buffer boofer;
	DatagramSocket sock;
	InetAddress destIP;
	int destPort;
	int counter = 1;
	byte[] one;
	byte[] two;
	byte[] three;

	public Extractor(DataSource src, InetAddress ip, int port){
		//DataSource containing the digitized audio stream is a push-type stream
		streams = ((PushBufferDataSource)src).getStreams();

		// There's only a single audio stream in the DataSource
		streams[0].setTransferHandler(this);

		ds = src;
		buff = new Buffer();
		boofer = new Buffer();

		ls = new LiveStream();

		try{
			sock = new DatagramSocket();
		}catch(SocketException se){
			System.err.println("Failed to open socket.");
		}

		destIP = ip;
		destPort = port;

		System.out.println("::Destination Host identified as: " + destIP + "/" + port);
	}

	public LiveStream getLiveStream(){
		return ls;
	}

	public PushBufferStream getStream(){
		return streams[0];
	}

	public void start() {
		try {
			ds.start();
		} catch (IOException e) {
			System.err.println(e);
		}
	}

	public void stop() {
		try {
			ds.stop();
		} catch (IOException e) {
			System.err.println(e);
		}
	}

	/** This will get called when there's data pushed from the PushBufferDataSource. */
	public void transferData(PushBufferStream stream) {
		try {
			stream.read(buff);
		} catch (IOException e) {
			System.err.println(e);
			return;
		}
		transmit(buff);
	}

	void transmit(Buffer buffer) {
		/** Extracted byte[] debug messages **/
		/*
		System.out.println("Read audio data:");
		System.out.println("  Time stamp: " + buffer.getTimeStamp());
		System.out.println("  Sequence #: " + buffer.getSequenceNumber());
		System.out.println("  Data length: " + buffer.getLength());
		System.out.println("  Data Format: " + buffer.getFormat());
		System.out.println("  Header: " + buffer.getHeader()); //32864
		System.out.println("  Flags: " + buffer.getFlags());

		System.out.println(((byte[])buffer.getData()).length);
		System.out.println("  Data: ");
		byte[] temp = (byte[])buffer.getData();
		for(int i=0;i<temp.length;i++){
			System.out.print(temp[i]+" ");
		}System.out.println("");
		 */

		/** TRANSMIT CODE **/

		byte[] toSend = (byte[])buffer.getData();
		System.out.println(toSend.length);

		if(counter==1){
			one = toSend;

			byte[] withHeader = new byte[toSend.length+1];
			System.arraycopy(toSend,0,withHeader,1,toSend.length);
			withHeader[0]=(byte)counter;
			counter++;
			try{
				sock.send(new DatagramPacket(withHeader,0,withHeader.length,destIP,destPort));
				System.out.println("Sent Packet...");
			}catch(Exception e){
				System.err.println("Failed to send packet, SeqNo: "+buffer.getSequenceNumber());
			}
		}
		else{
			three = new byte[toSend.length];
			two = toSend;
			for(int i=0;i<toSend.length;i++){
				three[i]=(byte)(one[i]^two[i]);
				//System.out.println("Pkt:"+buffer.getSequenceNumber()+" "+three[i]);
			}
			byte[] withHeader = new byte[toSend.length+1];
			System.arraycopy(toSend,0,withHeader,1,toSend.length);
			withHeader[0]=(byte)counter;
			counter++;
			try{
				sock.send(new DatagramPacket(withHeader,0,withHeader.length,destIP,destPort));
				System.out.println("Sent Packet...");
			}catch(Exception e){
				System.err.println("Failed to send packet, SeqNo: "+buffer.getSequenceNumber());
			}
			withHeader = new byte[three.length+1];
			System.arraycopy(three,0,withHeader,1,three.length);
			withHeader[0]=(byte)counter;
			counter=1;
			try{
				sock.send(new DatagramPacket(withHeader,0,withHeader.length,destIP,destPort));
				System.out.println("Sent Packet...");
			}catch(Exception e){
				System.err.println("Failed to send packet, SeqNo: "+buffer.getSequenceNumber());
			}
		}

		/** Testing locally, build stream from "received" packets. **/
		//ls.update((byte[])buffer.getData());

		/** Testing locally, received stream debug messages. **/
		/*
		try{
			ls.read(boofer);
		}catch(IOException e){
			System.err.println(e);
		}
		System.out.println("DEBUG:::::::::::");
		System.out.println(boofer.getTimeStamp());
		System.out.println(boofer.getSequenceNumber());
		System.out.println(boofer.getLength());
		System.out.println(boofer.getFormat());
		System.out.println((byte[])boofer.getData());
		byte[] tempp = (byte[])boofer.getData();
		for(int i=0;i<tempp.length;i++){
			System.out.print(tempp[i]+" ");
		}System.out.println("");
		System.out.println("::::::::::::::::");

		for(int i=0;i<temp.length;i++){
			if(temp[i]!=tempp[i])
				System.out.println("NOT EQUAL@@@@@@@@@@@@@@@@@@@");
		}
		 */

		/*
		Object data = buffer.getData();
		if (data instanceof byte[]) {
			System.out.println("write byte array data");
			try {
				dout.write((byte[]) data);
				dout.flush();
			}
			catch (Exception e) {
				e.printStackTrace();
			}
		}
		if (buffer.isEOM())
			System.err.println("  Got EOM!");
		 */
	}

}

